package org.jackysoft.interceptor;

import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.jackysoft.entity.nosql.NameValuePair;
import org.jackysoft.entity.nosql.OperationLog;
import org.jackysoft.service.OperationLogService;
import org.jackysoft.util.Page;
import org.jackysoft.util.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class AbstractInterceptor extends HandlerInterceptorAdapter {

	protected final static Log logger = LogFactory
			.getLog(AbstractInterceptor.class);
	protected static final Set<String> excludes = Sets.newHashSet("page",
			"rows", "query.state");
	protected static final String BEAN_NAME = "bean";
	protected static final String BEANS_NAME = "beans";
	protected Object bean;
	protected Object beans;
	protected String servicePostFix = "ServiceImpl";
	protected Object service;

	protected ApplicationContext context;
	protected OperationLogService logService;

	/*****
	 * <pre>
	 * <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> 
	 * <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
	 * <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> 
	 * 	<property name="interceptors">
	 * 		<list>
	 * 			<bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/>
	 * 		</list>
	 * 	</property>
	 * </bean>
	 * <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
	 * </pre>
	 * 
	 * 
	 * 
	 ***/

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		logger.info("*********************preHandle********************");
		// @ModeAttribute
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		init(request, response, handler, modelAndView);

	}

	public void init(HttpServletRequest request, HttpServletResponse response,
			Object handler, ModelAndView modelAndView) throws Exception {
		HandlerMethod hm = (HandlerMethod) handler;
		bean = modelAndView.getModelMap().get(BEAN_NAME);
		beans = modelAndView.getModelMap().get(BEANS_NAME);
		String sname = bean.getClass().getSimpleName();
		sname = StringUtils.lowerFirstChar(sname);
		String beanName = sname + servicePostFix;
		service = context.getBean(beanName);
		fixPager(request, modelAndView);
		forLogged(request, hm);
		logger.info(" page fix post handle  runed and fix pager ");
	}

	protected void fixPager(HttpServletRequest request,
			ModelAndView modelAndView) {
		Page pager = (Page) modelAndView.getModelMap().get("pager");
		if (pager == null)
			return;

		String ajax = request.getParameter("ajaxable");

		if (ajax != null) {
			pager.setAjaxable(false);
		}

		Enumeration<String> names = request.getParameterNames();
		for (; names.hasMoreElements();) {
			String name = names.nextElement();
			if (excludes.contains(name))
				continue;
			String[] values = request.getParameterValues(name);
			for (String value : values) {
				if (value == null)
					continue;
				pager.addParameter(name, value);

			}

		}
		String requestURI = request.getRequestURI();
		pager.setRequestURI(requestURI);

		String ctxPath = request.getContextPath();
		;
		pager.setContextPath(ctxPath);
	}

	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		super.afterCompletion(request, response, handler, ex);
	}

	@Override
	public void afterConcurrentHandlingStarted(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		super.afterConcurrentHandlingStarted(request, response, handler);
	}

	public void setContext(ApplicationContext context) {
		this.context = context;
		logService = this.context.getBean(OperationLogService.class);
	}

	protected void forLogged(HttpServletRequest request, HandlerMethod hm)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, SecurityException, NoSuchMethodException {

		Subject subject = SecurityUtils.getSubject();
		Object user = subject.getPrincipal();
		OperationLog oprlog = new OperationLog();
		oprlog.setUser(user.toString());
		oprlog.setTarget(hm.getBeanType().getName());
		oprlog.setMethod(hm.getMethod().toString());
		Map<String, String[]> params = request.getParameterMap();
		List<NameValuePair> args = Lists.newArrayList();
		for (String key : params.keySet()) {
			String[] values = params.get(key);
			for (String value : values) {
				args.add(new NameValuePair(key, value));
			}
		}
		oprlog.setArgs(args);
		
		logService.save(oprlog);

	}
}